package com.zshan.clinic.common.util.decimal;


import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * RoundingMode.UP = ROUND_UP = 0 向远离0的方向进位 直接入 1.1 → 2，-1.1 → -2
 * RoundingMode.DOWN = ROUND_DOWN = 1 直接舍 1.9 → 1，-1.9 → -1
 * RoundingMode.CEILING = ROUND_CEILING =2 向正无穷方向进位 1.2 → 2，-1.2 → -1
 * RoundingMode.FLOOR = ROUND_FLOOR = 3 向负无穷方向进位 1.2 → 1，-1.2 → -2
 * RoundingMode.HALF_UP = ROUND_HALF_UP = 4 四舍五入 1.5 → 2，1.4 → 1，-1.5 → -2
 * RoundingMode.HALF_UP = ROUND_HALF_DOWN =5 五舍六入 1.5 → 1，1.6 → 2，-1.5 → -1
 * RoundingMode.HALF_EVEN = ROUND_HALF_EVEN = 6 向最接近的偶数舍入 1.5 → 2（因 2 是偶数） 2.5 → 2（因 2 是偶数） 3.5 → 4（因 4 是偶数）
 * RoundingMode.UNNECESSARY = ROUND_UNNECESSARY = 7 不允许有小数 1.0 → 1 ✅ 1.1 → ❌ 报错
 */
@Slf4j
public class BigDecimalUtils {

    /**
     * 保留两位小数
     */
    private static final int SCALE = 2;

    /**
     * 四舍五入
     */
    private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;

    /**
     * 向上取整
     */
    private static final RoundingMode ROUND_UP = RoundingMode.UP;


    private BigDecimalUtils() {}

    /** 加法 */
    public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
        return format(safe(v1).add(safe(v2)));
    }

    /** 加法 */
    public static BigDecimal add(BigDecimal v1, BigDecimal v2,int scale) {
        return format(safe(v1).add(safe(v2)),scale);
    }

    /** 减法 */
    public static BigDecimal subtract(BigDecimal v1, BigDecimal v2) {
        return format(safe(v1).subtract(safe(v2)));
    }

    /** 减法 */
    public static BigDecimal subtract(BigDecimal v1, BigDecimal v2,int scale) {
        return format(safe(v1).subtract(safe(v2)),scale);
    }

    /** 乘法 */
    public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) {
        return format(safe(v1).multiply(safe(v2)));
    }

    /** 乘法 */
    public static BigDecimal multiply(BigDecimal v1, BigDecimal v2,int scale) {
        return format(safe(v1).multiply(safe(v2)),scale);
    }

    /** 除法 */
    public static BigDecimal divide(BigDecimal v1, BigDecimal v2) {
        return divide(v1, v2, SCALE);
    }

    /**
     * 除法
     * @param v1
     * @param v2
     * @param scale
     * @return
     */
    public static BigDecimal divide(BigDecimal v1, BigDecimal v2, int scale) {
        if (safe(v2).compareTo(BigDecimal.ZERO) == 0) {
            throw new ArithmeticException("除数不能为0");
        }
        return safe(v1).divide(safe(v2), scale, ROUNDING_MODE);
    }

    public static BigDecimal divide(BigDecimal v1, BigDecimal v2, RoundingMode roundingMode,int scale) {
        if (safe(v2).compareTo(BigDecimal.ZERO) == 0) {
            throw new ArithmeticException("除数不能为0");
        }
        return safe(v1).divide(safe(v2), scale, roundingMode);
    }

    /** 返回保留两位小数、四舍五入的格式化值 */
    public static BigDecimal format(BigDecimal val) {
        return safe(val).setScale(SCALE, ROUNDING_MODE);
    }

    /** 返回保留两位小数、四舍五入的格式化值 */
    public static BigDecimal format(BigDecimal val,int scale) {
        return safe(val).setScale(scale, ROUNDING_MODE);
    }
    /** 返回保留两位小数、四舍五入的格式化值 */
    public static BigDecimal format(BigDecimal val,RoundingMode roundingMode,int scale) {
        return safe(val).setScale(scale, roundingMode);
    }

    /** 返回保留0位小数、四舍五入的格式化值 */
    public static Integer formatInt(BigDecimal val) {
        return safe(val).setScale(0, ROUNDING_MODE).intValue();
    }

    public static void main(String[] args) {
        System.out.println(formatInt(new BigDecimal("5.637")));
    }

    /** 大于 */
    public static boolean gt(BigDecimal v1, BigDecimal v2) {
        return safe(v1).compareTo(safe(v2)) > 0;
    }

    /** 小于 */
    public static boolean lt(BigDecimal v1, BigDecimal v2) {
        return safe(v1).compareTo(safe(v2)) < 0;
    }

    /** 等于 */
    public static boolean eq(BigDecimal v1, BigDecimal v2) {
        return safe(v1).compareTo(safe(v2)) == 0;
    }

    /** null 安全处理 */
    private static BigDecimal safe(BigDecimal val) {
        return val == null ? BigDecimal.ZERO : val;
    }

    /** String 转 BigDecimal（可选） */
    public static BigDecimal toBigDecimal(String val) {
        if (val == null || val.trim().isEmpty()) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(val.trim());
    }
}


